package ms.jacrim.pddl.viewer;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ms.jacrim.pddl.PddlSolution;

import org.eclipse.nebula.widgets.ganttchart.DefaultSettings;
import org.eclipse.nebula.widgets.ganttchart.GanttChart;
import org.eclipse.nebula.widgets.ganttchart.GanttComposite;
import org.eclipse.nebula.widgets.ganttchart.GanttEvent;
import org.eclipse.nebula.widgets.ganttchart.GanttSection;
import org.eclipse.nebula.widgets.ganttchart.ISettings;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;

public class SolutionPainter implements PaintListener {

	private PddlSolution solution;
	private GanttComposite chartComposite;
	private Map<String, Actor> actors;
	
	static class Actor {
		public String Name;
		public List<Goal> Goals = new ArrayList<Goal>();
		
		public static class Goal {
			public String Name;
			public int StartTime;
		}
	}
	
	public SolutionPainter(PddlSolution solution, TabFolder tabFolder, String name) {
		this.solution = solution;
		populateSolutionInfomation();
		createContent(name, tabFolder);
	}
	
	private void createContent(String name, TabFolder tabFolder) {
		TabItem goalListTabItem = new TabItem(tabFolder, SWT.NONE);
		goalListTabItem.setText(name);
		
		
		Composite composite = new Composite(tabFolder, SWT.NONE);
		composite.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
		composite.setLayout(new FillLayout());
		goalListTabItem.setControl(composite);
		
		SashForm sfHor = new SashForm(composite, SWT.VERTICAL);
		
		ViewForm vfTopView = new ViewForm(sfHor, SWT.NONE);
		ViewForm vfChart = new ViewForm(sfHor, SWT.BORDER);
		sfHor.setWeights(new int[] { 20, 80 });
		
		createGanttChart(vfChart);
	}

	private void createGanttChart(ViewForm vfChart) {
		
		int flags = 1 << 4;
		
		ISettings setting = createGanttSetting();
		
		GanttChart ganttChart = new GanttChart(vfChart, flags, setting);
		
		vfChart.setContent(ganttChart);
		
		chartComposite = ganttChart.getGanttComposite();
		
		
		for (Actor a : actors.values()) {
			GanttSection sec = new GanttSection(ganttChart, a.Name);
			Calendar calStart = Calendar.getInstance();
			for (Actor.Goal g : a.Goals) {
				Calendar calEnd = (Calendar) calStart.clone();
				calEnd.add(Calendar.MINUTE, 40);
				GanttEvent event = new GanttEvent(ganttChart, g.Name, calStart, calEnd, 0);
				sec.addGanttEvent(event);
				calStart = calEnd;
			}
		}
		
		chartComposite.jumpToEarliestEvent();
		
		
	}

	private ISettings createGanttSetting() {
		ISettings setting = new DefaultSettings() {
			@Override
			public Calendar getDDayRootCalendar() {
				Calendar now = Calendar.getInstance();
				return now;
			}
			
			@Override
			public boolean drawEventsDownToTheHourAndMinute() {
				return true;
			}
			
			@Override
			public int getInitialView() {
				return VIEW_DAY;
			}
			
			@Override
			public int getInitialZoomLevel() {
				return ZOOM_HOURS_MAX;
			}
			
			@Override
			public boolean enableDragAndDrop() {
				return false;
			}
			
			@Override
			public boolean enableResizing() {
				return false;
			}
			
			@Override
			public boolean lockHeaderOnVerticalScroll() {
				return true;
			}
		};
		return setting;
	}

	private void populateSolutionInfomation() {
		actors = new HashMap<String, Actor>();
		
		for(int i = 0; i < solution.ActionCount(); i ++) {
			PddlSolution.Action action = solution.getAction(i);
			if ("SATISFIES".equalsIgnoreCase(action.Name())) {
				Actor a = actors.get(action.Argument(0));
				if (a == null) {
					a = new Actor();
					a.Name = action.Argument(0);
					actors.put(a.Name, a);
				}
				Actor.Goal g = new Actor.Goal();
				g.Name = action.Argument(1);
				a.Goals.add(g);
			}
		}
	}
	
	@Override
	public void paintControl(PaintEvent e) {
		e.gc.drawString(String.format("This Solution have: %d actions", solution.ActionCount()), 50, 50);
	}

}
